﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace chore.Domain
{
    public class Occurrence
    {
        protected TimeSpan _frequency = TimeSpan.FromDays(1);

        public virtual long Id { get; set; }
        public virtual DateTime Starting { get; set; }
        public virtual TimeSpan Frequency
        {
            get { return _frequency; }
            set
            {
                if (value.TotalDays < 1)
                {
                    throw new InvalidValueException(
                        "Occurrence frequency cannot be less than 1 day. The default value of 1 day will be in effect until a valid value is provided");
                }
                _frequency = value;
            }
        }

        public virtual bool HasntStarted
        {
            get { return Starting > DateTime.Now; }
        }
        public virtual bool OccursToday
        {
            get { return GetStartDate().Equals(DateTime.Now.Date); }
        }


        public virtual DateTime GetNextOccurrence()
        {
            if (!HasntStarted)
            {
                return GetFutureDate();
            }
            else
            {
                return Starting;
            }
        }

        public virtual IEnumerable<DateTime> GetNextOccurrences(int numberOfOccurrencesToGet)
        {
            var firstDate = GetNextOccurrence();
            return BuildOccurrencesList(firstDate, numberOfOccurrencesToGet);
        }

        public virtual DateTime GetNextOccurrenceFrom(DateTime startDate)
        {
            if (!HasntStarted)
            {
                return GetFutureDate(startDate);
            }
            else
            {
                return Starting;
            }
        }

        public virtual IEnumerable<DateTime> GetNextOccurrencesFrom(int numberOfOccurrencesToGet, DateTime startDate)
        {
            var firstDate = GetNextOccurrenceFrom(startDate);
            return BuildOccurrencesList(firstDate, numberOfOccurrencesToGet);
        }

        protected virtual IEnumerable<DateTime> BuildOccurrencesList(DateTime firstDate, int numberOfOccurrencesToGet)
        {
            var dates = new List<DateTime>();
            dates.Add(firstDate);

            for (int i = 1; i < numberOfOccurrencesToGet; i++)
            {
                dates.Add(firstDate.AddDays(i * Frequency.Days));
            }

            return dates;
        }

        protected virtual DateTime GetFutureDate()
        {
            DateTime startDate = GetStartDate();
            return GetFutureDate(startDate);
        }

        protected virtual DateTime GetFutureDate(DateTime startDate)
        {
            if (startDate.Date > DateTime.Now.Date)
                return startDate.Date;
            return startDate.AddDays(Frequency.Days).Date;
        }

        protected virtual DateTime GetStartDate()
        {
            var daysSinceStart = DateTime.Now.Subtract(Starting);
            var occurrences = daysSinceStart.Days / Frequency.Days;
            var daysToAdd = occurrences * Frequency.Days;
            return Starting.AddDays(daysToAdd).Date;
        }
    }
}
